
local japi = require 'jass.japi'
local jass = require 'jass.common'
local dbg  = require 'jass.debug'
local utility = require 'util.utility'

local sync = {}
setmetatable(sync,sync)
sync.perfixs = {}
sync.alltriggers = {}
sync.allacts = setmetatable({}, {__mode = 'kv'})

ac.sync = sync

---全局事件回调
---@param name string 事件名称
---@param ... any 参数
function sync:notify(name, ...)
    local trigger = sync.alltriggers[name]
    if not trigger then return end
    for i = #trigger.actors, 1, -1 do 
        trigger.actors[i]:execute(...)
    end
end

---全局事件监听
---@param name string
function sync:register(name)
    local trigger = sync.alltriggers[name]
    if not trigger then
        trigger = ac.trigger.create(name)
        trigger.remove = function(t)
            for i = #trigger.actors, 1, -1 do 
                local act = trigger.actors[i]
                act:remove()
                sync.allacts[act] = nil
            end 
            sync.alltriggers[name] = nil
        end
        sync.alltriggers[name] = trigger
        local perfix = japi.md5(name)
        sync.perfixs[perfix] = name 
        sync.perfixs[name] = perfix
    end 
    return function (func)
        local act = trigger:add_actor(func)
        act.key = "同步事件>" .. name
        sync.allacts[act] = true
        return act
    end
end

sync.on     = sync.register
sync.event  = sync.register

--- 单个逻辑帧只能同步1次
local clock = os.clock()
---发起同步
function sync:__call(name, ...)
    local c = os.clock()
    if (c-clock) < 0.01 then 
        return 
    end 
    clock = c 
    local perfix = sync.perfixs[name]
    if not perfix then 
        return end
    local data = {...}
    table.insert(data, 1, perfix)
    table.insert(data, 1, jass.GetPlayerId(jass.GetLocalPlayer()))
    local message = string.format("%s",utility.encode(data))
    if message:len() > 1000 then
        print("字符串太长了",message,debug.traceback())
        return
    end
    japi.SendCustomMessage(message)
end

---private
local function init()
    local trigger = jass.CreateTrigger()
    dbg.handle_ref(trigger)

    local function _action()
        local message = japi.GetTriggerMessage()
        local player = japi.GetMessagePlayer()
        --不允许有括号
        if message:find('%(') or message:find("%)") then
            return
        end
        local ok, res = pcall(utility.decode, message)
        if not ok or not res then
            return
        end
        local id, perfix = res[1], res[2]
        if (jass.GetPlayerId(player)) ~= id or perfix == nil then 
            return 
        end 
        local name = sync.perfixs[perfix]
        if not name then 
            return 
        end 
        local player = (ac.player and ac.player(player) or player)
        sync:notify(name, player, select(3, table.unpack(res) ))
        player:notify('玩家-刷新UI',player)
    end
    jass.TriggerAddAction(trigger, _action)

    if japi.DzTriggerRegisterSyncData then
        rawset(japi,'GetMessagePlayer', japi.DzGetTriggerSyncPlayer)
        rawset(japi,'GetTriggerMessage', japi.DzGetTriggerSyncData)
        rawset(japi,'SendCustomMessage', function (message)
            japi.DzSyncData('sync', message)
        end)
        japi.DzTriggerRegisterSyncData(trigger,'sync',false)
    else
        japi.RegisterMessageEvent(trigger)
        --魔兽版本非124的情况下该同步会出现奇怪的问题
        --所以默认选用dz同步
    end
end

init()

return sync